package promote.brozen.algorithm.tree.balance.bt;

import lombok.Getter;
import lombok.Setter;

/**
 * @author Brozen
 * @date 2020/1/13 4:21 PM
 */
@Getter
@Setter
public class BTreeNode<K extends Comparable<K>> {

    private BTreeChildChainNode<K> parent;

    private BTreeChildChainNode<K> head;

    private BTreeChildChainNode<K> tail;

    private int keySize;

    private boolean isLeaf;

    public BTreeNode() {
        this(null);
    }

    public BTreeNode(K key) {
        this.head = new BTreeChildChainNode<>(this);
        this.tail = new BTreeChildChainNode<>(this);
        this.isLeaf = true;

        if (key != null) {
            BTreeDataChainNode<K> dataChainNode = new BTreeDataChainNode<>(this, key);
            this.head.setNext(dataChainNode);
            dataChainNode.setPrev(this.head);
            this.tail.setPrev(dataChainNode);
            dataChainNode.setNext(this.tail);
            this.keySize = 1;
        }
    }

    public BTreeDataChainNode<K> getDataChainNode(int i) {
        BTreeDataChainNode<K> dataChainNode = this.head.getNext();
        int counter = 0;
        while (dataChainNode != null) {
            if (i == counter) {
                return dataChainNode;
            }

            counter++;
            dataChainNode = dataChainNode.getNext().getNext();
        }

        throw new ArrayIndexOutOfBoundsException("BTreeNode chain don't have a data chain node at "
                + i + ". Max key size is " + keySize);
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder("BTreeNode[size=").append(keySize).append(", chain=[");
        BTreeChildChainNode node = this.head;
        do {
            str.append("[child↓").append(node.toString()).append("] -> ");
            BTreeDataChainNode dataNode = node.getNext();
            if (dataNode != null) {
                str.append("[key=").append(dataNode.getKey()).append("] -> ");
            }
            node = dataNode == null ? null : dataNode.getNext();
        } while (node != null);
        str.append("]]");
        return str.toString();
    }

}
